package com.pitop.base.ctrl;

import com.auth0.jwt.JWTCreator;
import com.opensso.sdk.tools.SessionTools;
import com.pitop.account.entity.Account;
import com.pitop.account.service.AccountSVImpl;
import com.pitop.account.vo.AccountVO;
import com.pitop.core.entity.BeanRet;
import com.pitop.core.enums.SessionEnum;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.tools.JwtToken;
import com.pitop.core.tools.StringTools;
import com.pitop.core.tools.redis.RedisUtils;
import com.pitop.setting.entity.Setting;
import com.pitop.setting.service.SettingSVImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 登录，退出控制器
 * 在未使用open-sso时，使用该登录方法；使用open-sso时，废弃该登录和退出方法
 * Created by jiyan on 2019/4/9.
 */
@RestController
@RequestMapping("/login")
@Slf4j
@Api(value = "登录控制器", description = "登录控制器")
public class LoginCtrl {

    @Autowired
    private AccountSVImpl accountSVImpl;

    @Autowired
    private SettingSVImpl settingSVImpl;

    @Resource
    private RedisUtils redisUtils;

    /**
     * 登录
     * 1.参数非空验证
     * 2.用户信息是否存在
     * 3.生成会话
     * 4.保存到redis
     *
     * @return BeanRet
     */
    @ApiOperation(value = "登录", notes = "登录")
    @GetMapping(value = "/login")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "账户信息", paramType = "query", required = true),
            @ApiImplicitParam(name = "password", value = "密码", paramType = "query", required = true),
    })
    @ResponseBody
    public BeanRet login(String account, String password, HttpServletRequest request, HttpServletResponse response) {
        //1.参数非空验证
        Assert.hasText(account, BaseException.BaseExceptionEnum.Empty_Param.toString());
        Assert.hasText(password, BaseException.BaseExceptionEnum.Empty_Param.toString());
        //session和token有效时间
        Setting session_Expire_TimeSetting = settingSVImpl.loadByK(Setting.Key.Session_Expire_Time.name());//会话过期时间
        int session_Expire_Time = Integer.parseInt(session_Expire_TimeSetting.getV());
        Setting token_Expire_TimeSetting = settingSVImpl.loadByK(Setting.Key.Token_Expire_Time.name());//token过期时间
        long token_Expire_Time = Long.parseLong(token_Expire_TimeSetting.getV());
        //2.检查是否已经登录过.
        String sessionkey = SessionTools.Instance.genSessionKey(account);
        AccountVO accountVO= (AccountVO) redisUtils.get(sessionkey);
        if(accountVO != null) {
            response.addHeader(SessionEnum.authorization.name(), accountVO.getToken());
            return BeanRet.create(true, BaseException.BaseExceptionEnum.Success, accountVO.getToken());
        }
        //3.用户信息是否存在
        Account accountFlag = accountSVImpl.loadByAccountAndPwd(account, password);
        if (accountFlag == null) {
          return  BeanRet.create(false, BaseException.BaseExceptionEnum.Result_Not_Exist);
        }
        //生成JWT会话
        JWTCreator.Builder builder = JwtToken.create();
        builder.withClaim(SessionEnum.SessionKey.name(), sessionkey)
                .withClaim(SessionEnum.Code.name(), accountFlag.getCode())
                .withClaim(SessionEnum.Session.name(), SessionEnum.Account.name())
                .withClaim(SessionEnum.Account.name(), account)
                .withClaim(SessionEnum.Session_Expire_Time.name(), String.valueOf(session_Expire_Time));

        //生成token前端缓存使用
        Setting token_SecretSetting = settingSVImpl.loadByK(Setting.Key.Token_Secret.name());
        String token = JwtToken.createToken(builder, token_SecretSetting.getV(), token_Expire_Time);
        //Account转化为VO对象
        accountVO = StringTools.convertObject(accountFlag, AccountVO.class);
        accountVO.setToken(token);
        redisUtils.set(sessionkey, accountVO, session_Expire_Time);
        response.addHeader(SessionEnum.authorization.name(), token);
        return BeanRet.create(true, BaseException.BaseExceptionEnum.Success, token);
    }


    /**
     * 注销登录
     *
     * @param response response对象
     * @return BeanRet
     */
    @ApiOperation(value = "注销登录")
    @RequestMapping(value = "logout", method = RequestMethod.GET)
    @ResponseBody
    public BeanRet logout(HttpServletResponse response, HttpServletRequest request) {
        //1.获取token
        String authorization = request.getHeader(SessionEnum.authorization.name());

        String sso_secret = settingSVImpl.loadByK(Setting.Key.Token_Secret.name()).getV();
        String account = com.pitop.core.tools.JwtToken.getTokenValue(authorization, sso_secret, SessionEnum.Account.name());
        if (StringTools.isEmpty(account)) {
            return BeanRet.create(true, BaseException.BaseExceptionEnum.Success);
        }
        //2.删除缓存
        String sessionKey = SessionTools.Instance.genSessionKey(account);
        redisUtils.del(sessionKey);
        return BeanRet.create(true, BaseException.BaseExceptionEnum.Success);
    }
}
